﻿using System;
using System.Collections;
using System.Collections.Generic;
using System.Drawing;
using System.Drawing.Imaging;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Xml.Serialization;

namespace VMS.FTS.APPPUSH.Utils.FontData
{
    public class FUtils
    {
        private static FUtils _instance;
        private static object lockObj = new object();

        // Constructor is 'protected'
        protected FUtils()
        {
        }

        public static FUtils Instance()
        {
            lock (lockObj)
            {
                if (_instance == null)
                {
                    _instance = new FUtils();
                }
            }

            return _instance;
        }

        public List<TextLineElement> GetTextElementList(string content, string delimiter, string color, byte size = 8, int width = 144, int height = 96, bool isFontSizeFlex = true)
        {
            content = content.ToUpper();
            List<TextLineElement> elementList = new List<TextLineElement>();
            string[] contentArr = content.Split(new string[] { delimiter }, StringSplitOptions.RemoveEmptyEntries);

            int spacing = height / contentArr.Length;
            int currentPos = 0;

            if (isFontSizeFlex)
            {
                size = (byte)(contentArr.Length == 3 ? 12 : contentArr.Length == 4 ? 10 : 8);
            }

            foreach (string str in contentArr)
            {
                elementList.Add(new TextLineElement(currentPos * spacing, 0, str, GetState(color), size));
                currentPos++;
            }
            return elementList;
        }

        public int GetState(string color)
        {
            Element.Color vmsColor = (Element.Color)System.Enum.Parse(typeof(Element.Color), color);
            return vmsColor.GetHashCode();
        }

        public CustomElement GetBorderElement(Document document, int elementState = 1)
        {
            StringBuilder sb = new StringBuilder();

            for (int x = 0; x < document.Width; x++)
            {
                if (x % 6 < 3)
                {
                    sb.Append(x.ToString() + ",0,");
                    sb.Append(x.ToString() + "," + (document.Height - 1).ToString() + ",");
                }
            }

            for (int x = 1; x <= document.Height; x++)
            {
                if (x % 6 < 3)
                {
                    sb.Append("0," + x.ToString() + ",");
                    sb.Append((document.Width - 1).ToString() + "," + x.ToString() + ",");
                }
            }

            CustomElement element = new CustomElement(document.Height, document.Width, sb.ToString().Substring(0, sb.ToString().Length - 1));
            element.Clickable = true;
            element.State = elementState;
            return element;

        }

        public Bitmap ToBitmap(Document document)
        {
            document.Draw();
            Bitmap bmp = new Bitmap(document.Width, document.Height, PixelFormat.Format16bppRgb555);

            for (int x = 0; x < document.Width; x++)
            {
                for (int y = 0; y < document.Height; y++)
                {
                    Point p = document.PointArray[x, y];
                    if (p == null)
                    {
                        //result.SetPixel(x, y, Color.Black);
                    }
                    else
                    {
                        bmp.SetPixel(x, y, p.Color);
                    }
                }
            }

            //Bitmap result = Indexed8BitImageConverter.ConvertTo8bppFormat(bmp);
            return bmp;
        }

        public byte[] ToBinary(Document document)
        {
            document.Draw();

            int BPP = 1;// 1 bits per pixels
            // alloc memory array
            BitArray bArray = new BitArray(document.Width * document.Height * BPP);
            // copy pixel from bitmap to led bit matrix
            for (int j = 0; j < document.Height; j++)
            {
                for (int i = 0; i < document.Width; i++)
                {
                    Point point = document.PointArray[i, j];

                    if (point == null || point.Color.ToArgb() != Color.Red.ToArgb())
                    {

                        bArray[j * document.Width * BPP + i] = false;
                    }
                    else
                    {
                        bArray[j * document.Width * BPP + i] = true;
                    }
                }
            }

            byte[] ret = new byte[(bArray.Length + 7) / 8 + 1];

            // Data format:
            // <width><data>
            // <width> 1 byte
            ret[0] = (byte)document.Width;
            // <data>  bArray.Length/8 bytes
            bArray.CopyTo(ret, 1);

            return ret;

        }

        public void ClickOnDocument(Document document, int x, int y)
        {
            document.Draw();
            document.Clicked(x, y);
        }

        public void Serialize(string fileName, Document document)
        {
            XmlSerializer xmlSerializer = new XmlSerializer(typeof(Document));
            TextWriter writer = new StreamWriter(fileName);
            xmlSerializer.Serialize(writer, document);
        }

        public void Serialize(Stream stream, Document document)
        {
            XmlSerializer xmlSerializer = new XmlSerializer(typeof(Document));
            xmlSerializer.Serialize(stream, document);
        }

        public string Serialize(Document document)
        {
            using (MemoryStream stream = new MemoryStream())
            {
                Serialize(stream, document);
                stream.Position = 0;
                StreamReader reader = new StreamReader(stream);
                return reader.ReadToEnd();
            }
        }

        //public Document Deserialize(string fileName)
        //{
        //    XmlSerializer xmlSerializer = new XmlSerializer(typeof(Document));
        //    TextReader reader = new StreamReader(fileName);
        //    return (Document)xmlSerializer.Deserialize(reader);
        //}

        public Document Deserialize(Stream stream)
        {
            long pos = stream.Position;
            XmlSerializer xmlSerializer = new XmlSerializer(typeof(Document));
            stream.Position = 0;
            return (Document)xmlSerializer.Deserialize(stream);
        }

        public Document Deserialize(string content)
        {
            using (MemoryStream stream = new MemoryStream(UnicodeEncoding.UTF8.GetBytes(content)))
            {
                return Deserialize(stream);
            }
        }
    }
}
